import json
import os
import string
import sys
import time
from typing import List
from urllib.parse import urlparse

import Levenshtein
import boto3
import requests
from botocore.exceptions import ClientError
from nltk.corpus import words
from nltk.stem import WordNetLemmatizer

from product_upload.domain.basic.basic_image import BasicImage
from product_upload.domain.basic.basic_supplier import BasicSupplier
from product_upload.util.basic.common_util import sleep_random_duration
from product_upload.util.basic.mysql_util import db_list_by_page, db_batch_update
from product_upload.util.seller.amazon_us_util import old_get_common_data

password = "hunan2025_rmd_qulai$#@"

aws_bucket_base_api = "https://hunan0424.s3.us-east-2.amazonaws.com/"

CHARSET = string.ascii_lowercase[:16]
HALF_BYTE_SIZE = 16


def map_to_charset(byte, charset=CHARSET):
    high_half = byte >> 4
    low_half = byte & 0xF
    return charset[high_half] + charset[low_half]


def unmap_from_charset(char_pair, charset=CHARSET):
    high_char, low_char = char_pair
    high_half = charset.index(high_char)
    low_half = charset.index(low_char)
    return (high_half << 4) | low_half


def xor_crypt_string(data, key):
    return bytes(a ^ b for a, b in zip(data, key * (len(data) // len(key) + 1)))


def encrypt(plain_text):
    encrypted_bytes = xor_crypt_string(plain_text.encode('utf-8'), password.encode('utf-8'))
    return ''.join(map_to_charset(b) for b in encrypted_bytes)


def decrypt(cipher_text):
    if len(cipher_text) % 2 != 0:
        raise ValueError("Cipher text length must be even.")
    byte_pairs = [cipher_text[i:i + 2] for i in range(0, len(cipher_text), 2)]
    decrypted_bytes = bytes(unmap_from_charset(pair) for pair in byte_pairs)
    return xor_crypt_string(decrypted_bytes, password.encode('utf-8')).decode('utf-8', errors='ignore')


# aws lambda方式
def lambda_handler(event, context):
    request_str = event.get('body')
    req_data = json.loads(request_str)
    # req_data = event
    token = req_data.get('token', '')
    if token != '&%@*XHfbs_lucky_rmd_qulai_2025..*#@#df.':
        return {
            'statusCode': 500,
            'body': "大哥求放过...Boss, please forgive me.."
        }
    # 从事件中获取URL、S3桶名和文件键（S3的存储路径）
    url = req_data.get('url', '')
    content_type = req_data.get('content_type', '')
    s3_bucket = req_data.get('s3_bucket', '')
    s3_key = req_data.get('s3_key', '')

    max_retries = 2
    retries = 0
    while retries <= max_retries:
        try:
            response = requests.get(url)
            response.raise_for_status()
            s3 = boto3.client('s3')
            s3.put_object(Bucket=s3_bucket, Key=s3_key, Body=response.content, ContentType=content_type)
            break
        except Exception as e:
            retries += 1
            if retries > max_retries:
                return {
                    'statusCode': 500,
                    'body': f'Failed to download file after {max_retries + 1} attempts: {e}'
                }
            time.sleep(2)
    return {
        'statusCode': 200,
        'body': 'File successfully uploaded to S3'
    }


# 根据桶名称和key检测文本，返回 检测到的文本内容列表
def detect_text(bucket_name, bucket="hunan0424"):
    text_list = []
    try:
        session = boto3.Session(profile_name='default')
        client = session.client('rekognition')
        response = client.detect_text(Image={'S3Object': {'Bucket': bucket, 'Name': bucket_name}})
        # 提取检测到的文本
        text_detections = response['TextDetections']
        for text in text_detections:
            text_list.append(text['DetectedText'])
        return text_list
    except ClientError as e:
        error_code = e.response['Error']['Code']
        # 检查是否是欠费或服务不可用
        if error_code == 'InsufficientBalance':
            print("账户欠费，无法处理请求。停止当前线程。")
            sys.exit(0)
        elif error_code == 'ServiceUnavailable':
            print("服务不可用，请稍后再试。停止当前线程。")
            sys.exit(0)
        else:
            print(f"请求失败，错误代码: {error_code}, 错误信息: {e}")
            return text_list
    except Exception as e:
        print(f"发生了一个未知错误: {e}")
        return text_list


from concurrent.futures import ThreadPoolExecutor, as_completed


# 获取ocr结果,并保存到数据库,提供给外部调用
def aws_ocr_new_product(platform):
    sensitive_map = old_get_common_data()["sensitive"]
    brand_words = [word for key, values in sensitive_map.items() if key not in ["need_filter_field"] for word in values]
    brand_words_lower = [x.lower() for x in brand_words]
    with ThreadPoolExecutor(max_workers=10) as executor:
        futures = []
        for page in range(1, 9999999):
            basic_image_list = db_list_by_page("basic_image", ",".join(BasicImage.fields),
                                               f"platform='{platform}' and published = 1 and ocr_status = 1 and status !=2 and update_by ='' and main_image like 'https://hunan0424%' ",
                                               BasicImage, page, 100)
            if len(basic_image_list) == 0:
                break  # 如果没有数据，退出循环
            # 提交线程任务
            futures.append(executor.submit(thread_ocr_res, page, basic_image_list, brand_words, brand_words_lower))
            # 控制请求的时间间隔
            sleep_random_duration()
        # 等待线程池中的所有任务完成
        print("OCR scan wait all thread...")
        for future in as_completed(futures):
            try:
                future.result()  # 获取线程执行的返回值，或捕获异常
            except Exception as e:
                print(f"task exec fail: {e}")
        print("OCR scan all thread end...")


def thread_ocr_res(thread_id, _images_res: List[BasicImage], brand_words, brand_words_lower):
    for out_index, basic_image in enumerate(_images_res):
        ocr_res_dict = json.loads(
            basic_image.ocr_result) if basic_image.ocr_result is not None and basic_image.ocr_result != "" else {}
        ocred_index = list(ocr_res_dict.keys()) if ocr_res_dict else []
        images_list = [basic_image.main_image, basic_image.other_image_url1, basic_image.other_image_url2,
                       basic_image.other_image_url3, basic_image.other_image_url4, basic_image.other_image_url5,
                       basic_image.other_image_url6, basic_image.other_image_url7, basic_image.other_image_url8,
                       basic_image.other_image_url9, basic_image.other_image_url10, basic_image.other_image_url11,
                       basic_image.other_image_url12, basic_image.other_image_url13, basic_image.other_image_url14,
                       basic_image.other_image_url15]
        images_list = [x for x in images_list if x is not None and x != ""]
        ocr_status = 2
        status = 3
        for in_index, image in enumerate(images_list):
            if not image.startswith("https://hunan0424"):
                db_batch_update("basic_image", ["id", "status", "ocr_status", "remark"],
                                [[basic_image.id, 0, 1, "有未上传S3的图"]])
                break
            bucket_name_ = image.replace("https://hunan0424.s3.us-east-2.amazonaws.com/", "")
            index = bucket_name_.split("_")[1]
            ocr_res = []
            if str(index) in ocred_index:
                ocr_res = ocr_res_dict.get(str(index), [])
            else:
                det_text = detect_text(bucket_name_)
                ocr_res = list(set(det_text))
            status, image_flag = is_contains_brand(index, ocr_res, brand_words, brand_words_lower, ocr_res_dict)
            ocr_res_dict[str(index)] = ocr_res
            if image_flag:
                ocr_res_dict["inch_url"] = [image]
                # 遇到不上架状态，和待检验可以提前结束该sku
            if status == 4 or status == 0:
                ocr_status = 3
                break
        if status == 1:
            if ocr_res_dict.get("hit_word"):
                status = 3
                ocr_status = 3
        db_batch_update("basic_image", ["id", "ocr_result", "status", "ocr_status"],
                        [[basic_image.id, json.dumps(ocr_res_dict), status, ocr_status]])
    print(f'OCR scan end:thread_page:{thread_id}')


def is_contains_brand(index, words_list, brand_words_, brand_words_lower_, ocr_res_dict):
    # 1=正常，0待校验，2不上架,3半通过，4 OCR不上架
    if words_list is None or len(words_list) == 0:
        return 1, False
    if all(len(word) == 1 for word in words_list):
        return 1, False
    contains_digit = []
    _status = 1
    for word in words_list:
        if word.lower().strip() in brand_words_ or word.lower().strip() in brand_words_lower_:
            ocr_res_dict["hit_word"] = [f"apiocr_全等:图{index},{word}"]
            return 4, False
        if is_word_in_dictionary(word.strip()) or all(
                is_word_in_dictionary(split.replace(" ", "").strip()) for split in word.split(":") if
                len(split) > 1) or all(
                is_word_in_dictionary(split.replace(":", "").strip()) for split in word.split(" ") if len(split) > 1):
            continue
        if word.startswith("http") or word.startswith("apiocr_"):
            continue
        if "®" in word:
            ocr_res_dict["hit_word"] = [f"apiocr_商标:图{index},{word}"]
            return 4, False
            # 检查单词是否包含数字
        if any(char.isdigit() for char in word):
            contains_digit.append(word)
            continue
        for bw in brand_words_:
            similarity = Levenshtein.ratio(word, bw)
            if similarity >= 0.8 and abs(len(word) - len(bw)) == 0 and len(word) >= 3:
                ocr_res_dict["hit_word"] = [f"apiocr_相似度大于80%:图{index},{word}----{bw}"]
                return 0, False
            elif similarity >= 0.7 and abs(len(word) - len(bw)) == 0 and len(word) >= 3:
                if _status == 1:
                    ocr_res_dict["hit_word"] = [f"apiocr_相似度大于70%:图{index},{word}----{bw}"]
                    _status = 3
    # 如果超过四分之三的单词包含数值，则返回1
    if len(contains_digit) > (3 * len(words_list)) / 4:
        return 1, True
    # 如果没有任何符合品牌词规则的情况，返回3
    return _status, False


lemmatizer = WordNetLemmatizer()


def is_word_in_dictionary(word):
    word = lemmatizer.lemmatize(word.lower())  # 将输入转换为小写以确保大小写不敏感
    word_list = set(words.words())  # 获取所有单词，并将其存储在一个集合中以加快查找速度
    return word in word_list


def create_directory(path):
    try:
        if not os.path.exists(path):
            os.makedirs(path)
    except OSError:
        pass


def download_file(url, save_path):
    for i in range(3):
        try:
            response = requests.get(url, stream=True, timeout=45)
            if response.status_code == 200:
                with open(save_path, 'wb') as f:
                    for chunk in response.iter_content(8192):
                        f.write(chunk)
                break
            elif response.status_code == 403:
                break
        except Exception as e:
            print(f"重试一次,下载 {url} 时出错: {e}")


def download_task(prod, base_dir):
    platform_dir = os.path.join(base_dir, prod.platform)
    product_type_dir = os.path.join(platform_dir, prod.product_type)
    sku_dir = os.path.join(product_type_dir, prod.sku)
    # 创建文件夹
    create_directory(platform_dir)
    create_directory(product_type_dir)
    create_directory(sku_dir)
    filter_url = ""
    if prod.ocr_result:
        collect = json.loads(prod.ocr_result)
        if collect.get("inch_url", []):
            filter_url = collect.get("inch_url")[0]
    for i in range(1, 16):
        zip_platform = "xl"
        if prod.platform == "DB":
            zip_platform = "doba"
        elif prod.platform == "GG":
            zip_platform = "gg"
        elif prod.platform == "SY":
            zip_platform = "sy"
        for last in ["jpg", "JPG", "png", "jpeg", "JPEG"]:
            file_url = f"https://hunan0424.s3.us-east-2.amazonaws.com/images/{zip_platform}/{str(prod.basic_id)}_{str(i)}_{encrypt(prod.sku)}.{last}"
            if filter_url:
                if f'{str(prod.basic_id)}_{str(i)}_{encrypt(prod.sku)}' in filter_url:
                    continue
            parsed_url = urlparse(file_url)
            file_name = os.path.basename(parsed_url.path)
            save_path = os.path.join(sku_dir, file_name)
            download_file(file_url, save_path)


# 主函数
def export_s3_img(basic_platform, base_dir=r'C:\Users\hunan\Desktop\gen_img'):
    # 获取产品列表
    supplier_list = db_list_by_page("basic_supplier", "code", f"status=1 and platform ='{basic_platform}'",BasicSupplier, 1, 9999)
    supplier_code_str = ",".join([f'"{x.code}"' for x in supplier_list])
    download_ids = ['72186', '49328', '49313', '49354', '49362', '49345', '49343', '42373', '42374', '74603', '1587', '1589', '1590', '1591', '39323', '32841', '25397', '24247', '22021', '22500', '22168', '19707', '26633', '145033', '35279', '42505', '42506', '53657', '53650', '40447', '38911', '38918', '38914', '694053', '48728', '24004', '38993', '38977', '142367', '83262', '145092', '145093', '145094', '145179', '145180', '141694', '81528', '51768', '51769', '55117', '45760', '34839', '34835', '45764', '45765', '45770', '45771', '54843', '42352', '1694', '9825', '79190', '834', '835', '15365', '15438', '23257', '5396', '18563', '2431', '664', '665', '248', '47068', '5617', '45738', '39623', '39247', '144042', '982', '378', '9826', '7304', '79189', '7305', '7306', '7307', '31699', '21593', '44961', '74590', '74604', '74598', '74596', '74595', '1652', '1653', '1654', '145214', '145215', '3644', '15678', '15677', '15133', '18182', '15361', '16822', '17874', '16454', '85899', '17998', '23086', '16149', '16148', '16394', '16391', '48215', '16349', '16450', '16145', '16147', '5395', '5399', '5400', '5397', '5401', '5398', '16401', '16400', '4247', '4365', '15293', '920', '34933', '2021', '5616', '39621', '92338', '7203', '7213', '8585', '55956', '43921', '1618', '15076', '614', '17712', '61645', '61623', '61615', '61616', '61624', '61625', '61605', '61648', '61606', '61639', '61611', '61636', '61641', '61644', '69425', '18227', '16083', '111', '16791', '18043', '403', '350', '33864', '33873', '33858', '693823', '16108', '16109', '16110', '17907', '17908', '17910', '14733', '16797', '16282', '2622', '17365', '150757', '150758', '150759', '150761', '150764', '150760', '3005', '16988', '17779', '17782', '51277', '51279', '51282', '18558', '51355', '43879', '18363', '18348', '141482', '74191', '68668', '68667', '68666', '142565', '71157', '71158', '71159', '22484', '33757', '33762', '39336', '24607', '42146', '142297', '62265', '89097', '74455', '71266', '66593', '66594', '66595', '67385', '67383', '67374', '35711', '63576', '65849', '66468', '66388', '65816', '66385', '58757', '58756', '58581', '58755', '58752', '53538', '53540', '53539', '53541', '46784', '29319', '29321', '29322', '50530', '42202', '42204', '42205', '56449', '32777', '53635', '53637', '53641', '53643', '43978', '43976', '43983', '43975', '43982', '39704', '39026', '39027', '38267', '39693', '39712', '693683', '693684', '150531', '693685', '150532', '34799', '22383', '22384', '22389', '22041', '22390', '142096', '141831', '141483', '141610', '142389', '150533', '142216', '142700', '142317', '40246', '87550', '34883', '30191', '30185', '30194', '30186', '30196', '30187', '30199', '44750', '35497', '35490', '34876', '21797', '92286', '92287', '92189', '92190', '93460', '93459', '150051', '150052', '35991', '35999', '35992', '36001', '51764', '51759', '28829', '25072', '58940', '58714', '58715', '59514', '58785', '55289', '55278', '50489', '52581', '19049', '59513', '54613', '55700', '69974', '27213', '5328', '80193', '144918', '93110', '52628', '39331', '18444', '89299', '47507', '47853', '47899', '46929', '31539', '47934', '47937', '29804', '18225', '51036', '32358', '22648', '22573', '47358', '47553', '51226', '17283', '16857', '16858', '16859', '55655', '55654', '7402', '53209', '2756', '14535', '22122', '22120', '17522', '17214', '54383', '53885', '54382', '53884', '53611', '53610', '60637', '15553', '15554', '4694', '16603', '17592', '60640', '60631', '60632', '60649', '60647', '60648', '60651', '60652', '60715', '60641', '17146', '60657', '15556', '60848', '60849', '60852', '16239', '17848', '60850', '53735', '15975', '4825', '53129', '53191', '53795', '53784', '17938', '53821', '17148', '17129', '22301', '52583', '144827', '6217', '38179', '47717', '31086', '42322', '48152', '22334', '24909', '17880', '17883', '24938', '24464', '18354', '28061', '28067', '35432', '8302', '19270', '19227', '33120', '19225', '19242', '19224', '19239', '19222', '19220', '37779', '37778', '19139', '23256', '21350', '21364', '19103', '23079', '21768', '21692', '22338', '56013', '45861', '15148', '47627', '47619', '22182', '49510', '49512', '48936', '27523', '27524', '22281', '149748', '11103', '44039', '19444', '19465', '44036', '43265', '43261', '19463', '43329', '43326', '21869', '19462', '19443', '19457', '43289', '65749', '43325', '54827', '54828', '54826', '54824', '57001', '60258', '18511', '18678', '18673', '34081', '11839', '10234', '10237', '11572', '12496', '92961', '13346', '24054', '22897', '92293', '18675', '7906', '7907', '7908', '7909', '80226', '18385', '18533', '145250', '11042', '17846', '16633', '14915', '14163', '14164', '27308', '15034', '22270', '21810', '15866', '15241', '49408', '19113', '33766', '33764', '33769', '21795', '88656', '9493', '7996', '37794', '17432', '56354', '7652', '8536', '10972', '41537', '18341', '16026', '16025', '15802', '10580', '10583', '65809', '59573', '53740', '23011', '23006', '23005', '23009', '23002', '22989', '22997', '22986', '22991', '22990', '22988', '22984', '22983', '22977', '22976', '22974', '22973', '42981', '22049', '65845', '18710', '90515', '11065', '71684', '15379', '1408', '1409', '1082', '8951', '9772', '15238', '12085', '12086', '12045', '14895', '16216', '14239', '15450', '15451', '15452', '15446', '15447', '15448', '16218', '16022', '16021', '16082', '16080', '39684', '93357', '93308', '38796', '37811', '37802', '141643', '22028', '10170', '10171', '13192', '13193', '12470', '9881', '68468', '27931', '30113', '142313', '141762', '145939', '141854', '142224', '142218', '39220', '39221', '39224', '23230', '23228', '39222', '37968', '145547', '145548', '16498', '49431', '15751', '10576', '12043', '8921', '15840', '15184', '16084', '16160', '16156', '22863', '16416', '24016', '22146', '9121', '1436', '2493', '15594', '15595', '15596', '17597', '17599', '17293', '10619', '17571', '9120', '1664', '45565', '143968', '15892', '17798', '17734', '17747', '17748', '13236', '16488', '16086', '16494', '10919', '52845', '29653', '45575', '29682', '9355', '15155', '14814', '16601', '55809', '15897', '15603', '15244', '9491', '15213', '74998', '146254', '146255', '146256', '146257', '48075', '17242', '16442', '16167', '85569', '85608', '11407', '32132', '17251', '24454', '24816', '24807', '693943', '36092', '21816', '694963', '9639', '9640', '9643', '10525', '9645', '9977', '10252', '10255', '9869', '12756', '19329', '21809', '9341', '28783', '40335', '90908', '25242', '49030', '49029', '141925', '150429', '150430', '150431', '150432', '24545', '24544', '52602', '52603', '52586', '52587', '52798', '52805', '52588', '52800', '150733', '150734', '150735', '36355', '50234', '50235', '50236', '50237', '33692', '22480', '22467', '90513', '57074', '38643', '42207', '42208', '7828', '7829', '28347', '28345', '28153', '54629', '14040', '48127', '48342', '56328', '29758', '29756', '29755', '22521', '694294', '29007', '29006', '92238', '8794', '42134', '8795', '47632', '41365', '41362', '23517', '53328', '63331', '63329', '23055', '147735', '143432', '147864', '143177', '3153', '3228', '1244', '1696', '17689', '56704', '68579', '19629', '74277', '24360', '51230', '15354', '47858', '47916', '32702', '53597', '53744', '53794', '53799', '53210', '47718', '43203', '27043', '23248', '21959', '10267', '1486', '55566', '37797', '71695', '18398', '41552', '43912', '43913', '31786', '65027', '65026', '65025', '65024', '65022', '65020', '65055', '65051', '65049', '65048', '63319', '65032', '65042', '65040', '65039', '65035', '9517', '3825', '27965', '7363', '7179', '7281', '28228', '6180', '6017', '12115', '4525', '5323', '19494', '3304', '4245', '302', '1344', '1346', '2120', '1348', '1169', '1170', '1171', '1191', '1192', '13772', '11690', '16237', '16158', '16235', '2166', '3006', '1562', '56330', '42241', '48257', '693713', '694287', '694288', '694290', '694291', '53241', '53237', '53256', '53253', '53252', '53232', '15582', '48282', '51698', '32952', '32949', '32973', '66405', '66406', '66407', '53448', '53234', '53246', '53238', '53263', '53222', '38055', '58831', '75575', '75578', '30533', '66705', '89283', '35703', '67585', '87614', '22054', '90974', '90978', '46747', '41731', '18433', '15226', '144035', '40720', '69956', '24056', '3394', '47988', '10679', '11741', '26555', '17238', '11743', '78332', '16131', '17243', '17894', '60169', '5088', '30541', '16732', '31103', '22867', '8259', '22118', '65881', '53006', '53014', '9753', '28074', '28076', '28062', '28070', '15132', '15267', '15915', '17436', '49731', '50097', '21691', '22345', '22341', '22223', '22224', '24335', '18509', '7395', '16189', '10114', '10110', '10039', '14554', '14584', '14556', '14585', '3038', '3040', '3305', '5034', '5035', '4246', '4248', '4363', '4366', '13958', '144758', '9862', '12770', '10079', '40331', '9093', '12757', '15629', '13689', '13691', '12453', '14551', '22851', '36141', '22525', '1739', '14353', '10264', '10301', '15868', '37792', '55638', '54173', '41735', '41734', '41750', '54337', '46748', '41729', '41732', '41733', '15256', '42832', '23003', '23001', '22993', '22987', '22992', '22979', '22972', '90516', '57070', '45131', '22239', '11826', '11127', '11128', '11129', '11131', '11132', '6887', '6888', '6889', '11134', '11135', '11136', '12089', '12090', '12091', '12092', '10777', '10782', '10783', '12185', '15770', '15110', '15112', '15113', '14631', '14632', '14633', '14634', '280', '281', '22275', '28158', '7837', '7831', '7832', '7836', '39226', '39225', '40695', '42133', '22875', '144087', '144085', '144086', '47636', '1663', '1666', '1667', '1668', '1669', '1670', '1671', '1672', '1673', '23091', '39987', '24221', '16192', '17785', '62188', '62189', '9542', '55650', '55648', '4950', '5837', '4875', '3830', '23254', '5355', '5356', '4393', '43263', '35572', '3923', '23501', '23502', '15520', '4345', '4346', '3749', '693973', '4256', '33337', '32482', '72522', '48218', '80239', '80243', '80240', '80241', '33349', '33348', '69977', '69962', '3463', '42174', '67973', '90240', '544', '148722', '149750', '149751', '149752', '89704', '21872', '2576', '2577', '38783', '47925', '39248', '42759', '2961', '64723', '23416', '72018', '72015', '72013', '72025', '72022', '72017', '72021', '72020', '72012', '72009', '66960', '69963', '69710', '69966', '143582', '143676', '147817', '53450', '25281', '15449', '67644', '67643', '32794', '32813', '67555', '67550', '2221', '2064', '2057', '2056', '2297', '2298', '19428', '18401', '18362', '18350', '18365', '18364', '18343', '51271', '51385', '51272', '51351', '61937', '61939', '61940', '38008', '37929', '38059', '37928', '81633', '88744', '88746', '88838', '22703', '22694', '72645', '81296', '15518', '36334', '45697', '53251', '53229', '53250', '53255', '22975', '77840', '29474', '29533', '32787', '55573', '22869', '34269', '8532', '2228', '2230', '2231', '3055', '2121', '3056', '3048', '2122', '2123', '3057', '335', '2041', '2521', '2318', '2256', '2254', '2255', '2517', '2518', '2512', '2192', '2165', '148568', '3630', '2388', '3629', '92423', '92424', '407', '2997', '2962', '22675', '2164', '2629', '3004', '3929', '3245', '2395', '2398', '33220', '23968', '47257', '765', '145638', '145639', '145640', '145641', '145642', '145643', '145644', '145645', '145646', '145647', '145648', '145649', '145650', '145651', '145652', '145653', '145654', '145655', '145656', '145657', '145658', '145659', '145660', '145661', '145667', '145668', '145669', '145670', '145671', '145672', '145673', '145674', '145675', '145676', '145677', '145678', '145679', '145680', '145681', '145682', '27536', '27539', '74597', '21808', '5758', '69975', '2584', '18271', '17909', '694720', '16592', '16593', '16631', '16632', '150763', '22636', '22200', '19208', '19195', '19182', '19174', '19168', '19175', '18514', '22429', '150185', '29998', '65016', '87874', '64777', '88160', '72820', '148236', '144223', '53502', '53265', '53672', '53670', '53660', '53644', '53642', '53086', '53678', '53505', '53646', '142231', '47347', '72430', '54212', '53106', '53287', '58447', '143540', '143288', '143249', '142927', '52621', '19565', '24786', '19454', '19452', '19482', '19459', '19460', '43292', '19445', '43307', '33085', '143202', '92886', '92867', '92885', '92863', '30388', '42239', '15583', '38707', '88431', '81298', '88223', '88220', '42681', '42357', '52855', '52852', '46257', '46264', '24003', '38959', '46218', '65423', '65421', '65420', '67153', '65419', '23543', '65102', '39576', '67462', '67466', '144186', '90641', '92887', '86486', '85524', '79297', '79295', '39471', '39103', '39100', '39066', '59560', '59561', '75148', '29018', '56456', '62285', '62286', '22757', '58617', '61747', '61748', '61749', '61746', '29022', '50928', '50944', '50942', '50938', '50936', '50932', '50535', '50533', '46234', '49395', '49396', '63275', '22743', '41505', '41483', '41482', '41481', '41479', '40232', '40233', '40235', '40234', '39169', '39176', '39175', '61532', '61533', '61534', '41083', '40591', '22759', '22751', '22755', '22775', '56315', '56316', '56313', '56319', '41557', '41559', '41530', '56632', '56636', '24053', '24052', '24050', '24051', '38976', '38983', '38996', '38998', '24563', '24565', '23350', '23349', '23363', '23347', '35714', '35704', '35716', '90642', '53350', '40499', '40496', '40500', '40495', '63638', '42471', '42476', '66359', '25245', '25247', '22667', '22671', '25250', '25249', '25243', '25246', '19645', '21321', '19945', '63659', '63801', '63798', '62370', '41496', '41763', '66466', '79225', '76247', '67762', '65273', '62313', '62312', '62311', '54836', '57211', '53427', '53426', '66585', '56434', '25076', '25074', '56433', '52866', '91673', '89612', '91682', '91684', '91685', '91695', '91535', '91536', '91537', '91538', '91539', '91540', '19277', '19269', '19267', '19257', '19255', '19275', '19271', '19244', '19263', '19260', '19243', '19237', '19236', '19249', '19264', '19272', '19273', '19274', '19251', '19265', '19252', '19248', '19253', '19230', '19241', '19261', '19234', '19258', '19245', '19266', '19246', '19259', '143268', '143409', '59077', '59033', '22126', '16380', '16381', '16382', '16383', '16315', '16317', '15137', '15138', '15139', '15140', '89298', '90238', '47666', '47838', '18189', '17944', '18217', '18320', '18287', '18291', '18293', '18190', '18317', '48445', '32675', '2898', '15298', '15299', '17028', '16556', '15937', '18059', '7536', '24382', '15061', '15066', '17724', '3762', '15144', '15146', '14727', '14729', '14730', '19112', '93539', '16465', '15521', '48878', '15593', '15949', '15950', '15951', '15394', '15395', '15396', '15393', '15083', '15009', '14768', '14770', '48253', '15292', '16220', '16835', '15839', '15989', '17405', '17943', '16634', '17466', '93355', '39329', '39628', '15390', '16496', '16501', '16502', '17406', '17407', '17408', '17409', '17410', '17411', '17412', '17413', '40647', '15010', '15011', '15012', '16548', '15013', '15657', '15658', '1216', '53473', '53463', '15210', '13933', '53893', '39182', '19884', '15015', '15054', '16165', '16191', '69957', '149760', '149765', '85882', '22985', '23223', '141649', '39223', '47437', '86635', '143279', '47987', '92816', '32676', '49628', '89692', '78337', '78336', '78327', '60167', '60177', '60168', '60166', '146358', '146359', '146360', '146362', '146363', '146367', '146370', '146377', '146378', '146379', '146381', '146382', '146383', '146384', '146385', '146386', '146387', '146392', '146393', '146394', '146396', '146397', '146398', '146399', '146400', '146401', '146403', '146404', '146405', '146406', '146407', '144108', '146408', '146409', '146410', '146411', '146413', '146414', '146415', '146416', '146418', '146419', '146420', '146421', '146428', '146429', '146430', '146431', '148433', '148434', '148476', '148477', '148492', '148493', '148496', '148501', '148509', '148544', '6425', '85570', '85624', '85627', '85578', '85586', '85641', '85654', '77509', '77305', '77339', '77354', '62740', '27758', '27760', '89303', '27751', '27695', '89314', '89313', '89778', '89773', '89179', '89606', '56041', '22788', '141768', '49845', '33720', '21776', '53092', '18664', '45724', '38017', '80144', '43397', '24241', '18949', '33313', '19427', '19622', '24253', '19634', '19616', '19618', '19440', '19442', '693953', '693957', '693956', '141863', '22285', '41840', '56812', '56808', '56816', '144078', '48237', '48894', '24023', '24022', '24028', '92897', '144616', '144617', '144618', '144620', '46777', '46776', '21602', '54030', '93430', '146190', '35267', '694260', '694261', '694262', '694263', '22162', '47633', '47635', '41359', '33572', '33577', '33579', '33574', '33581', '33571', '47921', '47922', '47923', '47926', '65551', '52595', '52425', '52597', '52598', '37595', '37596', '37597', '23139', '693705', '693707', '693709', '693710', '693711', '85108', '28775', '28776', '24992', '54599', '72520', '47081', '55873', '59014', '695031', '52860', '43151', '43148', '40162', '10723', '10725', '56948', '47927', '47929', '47658', '66601', '56890', '3003', '3166', '8824', '19464', '43294', '44484', '19439', '19438', '9221', '9222', '9218', '23252', '23253', '23315', '13242', '16360', '55369', '56624', '88432', '75475', '75373', '27301', '143457', '28139', '22147', '22148', '38229', '27555', '27559', '27557', '27562', '27548', '27551', '27556', '56551', '56556', '693716', '54597', '22835', '142985', '61180', '57289', '89132', '89131', '89129', '89128', '89126', '88880', '88879', '88878', '76623', '88877', '86773', '87647', '87646', '87645', '87644', '87643', '87641', '87642', '89345', '89358', '89354', '89355', '76833', '67614', '75535', '75534', '75533', '75531', '61521', '61522', '61364', '61365', '75574', '75630', '72631', '40420', '67715', '67716', '61523', '63208', '63235', '63213', '57326', '63247', '40264', '40265', '40266', '40267', '40324', '146071', '146073', '41903', '24617', '24619', '24620', '24624', '24625', '24623', '40254', '40260', '40262', '143379', '143208', '143125', '147838', '142996', '69973', '4498', '17241', '4731', '27352', '31793', '68561', '85956', '31433', '31496', '31817', '32086', '51040', '28027', '27823', '28276', '27994', '27988', '27748', '1157', '4165', '53738', '4954', '7698', '10190', '93106', '27455', '16639', '48163', '39120', '19349', '46438', '43085', '16504', '13302', '16206', '27646', '19704', '19703', '55102', '55105', '21770', '22933', '22937', '148584', '148585', '19493', '27554', '19715', '19765', '10977', '14583', '73986', '69976', '8902', '8903', '9092', '9367', '9368', '9369', '9361', '43152', '92933', '9292', '10066', '8842', '9459', '12771', '12772', '11513', '11324', '9094', '14431', '43304', '19040', '21371', '21979', '21969', '21980', '14830', '14352', '14705', '14598', '254', '1107', '2726', '2727', '1287', '11494', '1203', '83128', '24219', '693725', '65003', '21941', '80713', '8993', '12592', '12593', '12594', '11735', '12088', '15108', '22031', '22034', '7835', '47071', '1499', '1500', '18420', '21911', '40697', '14611', '22279', '19676', '19674', '18989', '18991', '91954', '144088', '53640', '34086', '90862', '1665', '1922', '21865', '1063', '69969', '66509', '67646', '57714', '67499', '64849', '53638', '33477', '150641', '150642', '47804', '47013', '47014', '66504', '19436', '32807', '79579', '79578', '143060', '142904', '142884', '57457', '145049', '148581', '40663', '40662', '33839', '33841', '68114', '56826', '67935', '57277', '28806', '65764', '87649', '68318', '142703', '40992', '23050', '34767', '87355', '89168', '89167', '90983', '68626', '68629', '68625', '39746', '39718', '39729', '59512', '68627', '58759', '58758', '67493', '33183', '86092', '68047', '68735', '57329', '56458', '86612', '61308', '86134', '85464', '60152', '92219', '149980', '14671', '58961', '42101', '35485', '46754', '69952', '44386', '39676', '39674', '39559', '39568', '39558', '24019', '38974', '43285', '19206', '43288', '19389', '43973', '15391', '15387', '23500', '44035', '53468', '87679', '47554', '56139', '28334', '46301', '40465', '46192', '46285', '37942', '36159', '22927', '36352', '36237', '22423', '22456', '22363', '47372', '83119', '55962', '27432', '27591', '143554', '143053', '86069', '56737', '86063', '86065', '86066', '60952', '56487', '56488', '46254', '145019', '145020', '63796', '150070', '150071', '150072', '694289', '40446', '40444', '40445', '64690', '52623', '18726', '18717', '18719', '18725', '40487', '43342', '67880']
    download_ids_str = ",".join([str(x) for x in download_ids])
    prod_list = db_list_by_page("basic_image", "basic_id,platform,product_type,sku,ocr_result",
                                f"basic_id not in ({download_ids_str}) and published = 1 and ocr_result like '%hit_word%' and status in(0,2,3,4) and platform ='{basic_platform}' and product_type not in ('wallart','WALL_ART') and  basic_id in (select id from basic_product where not_available not like '%amazon%' and quantity > 3 and price >= 30 and supplier_code in({supplier_code_str})) and class_name not in ('Clothes & Decoration', 'Jewelry','Automotive','Media products - books DVD Music software video')",
                                BasicImage, 1, 999999)
    # 加几笔：使用线程池实现多线程下载
    print(basic_platform, len(prod_list))
    with ThreadPoolExecutor(max_workers=16) as executor:
        futures = [executor.submit(download_task, prod, base_dir) for prod in prod_list]
        for future in as_completed(futures):
            try:
                future.result()
            except Exception as e:
                print(f"任务执行出错: {e}")


if __name__ == "__main__":
    export_s3_img("SY")
    export_s3_img("DB")
    export_s3_img("GG")
    pass
